package com.group.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;

import javax.annotation.PostConstruct;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.base.view.GeneralResult;
import com.group.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.mail.EmailException;
import org.apache.http.HttpStatus;
import org.apache.poi.ss.usermodel.Cell;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Validator;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartRequest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.base.view.BaseResult;
import com.group.dao.*;
import com.group.model.BackUser;
import com.group.model.SystemPara;
import com.group.model.User;
import com.group.util.DateEditor;
import com.group.util.NoteException;
import com.group.util.WeiXinConf;
import com.group.util.WeiXinUtils;

/**
 * 异常处理,日期处理
 *
 * @author zhaolei
 */
@Controller
public class BaseController {
	public static final String KEY_USER_IN_SESSION = "USER";

	static String biz = "fingo-auth";

	private static final Logger logger = LoggerFactory.getLogger(BaseController.class);
	// private static final int IMG_EXPIRE_TIME = 86400;

	@Autowired
	Validator validator;

	@Autowired
	BookDao bookDao;

	@Autowired
	GuessDao guessDao;

	@Autowired
	TickerService tickerService;

	@Autowired
	BookScheduleService scheduleService;

	@Autowired
	MessageDao messageDao;

	@Autowired
	NewsService newsService;

	@Autowired
	BBSDao bbsDao;

	@Autowired
	UserService userService;

	@Autowired
	TickerDao tickerDao;

	@Autowired
	GeneralBeanDao beanDao;

	@Autowired
	UserDao userDao;

	@Autowired
	NewsDao newsDao;

	@Autowired
	WeiXinUtils weiXinUtils;

	@Autowired
	MessageService messageService;

	@Autowired
	CasinoService casinoService;

	@Autowired
	ClokinDao clokinDao;

	@Autowired
	ClokinService clokinService;

	@Value("${wx.baseurl:test}")
	public String BASE_URL;

	@Value("${qy.baseurl:test}")
	public String QYBASE_URL;

	@Value("${wx.appid:wx2d63ebae87d8cb17}")
	public String APPID;

	@Value("${wx.secret:4caadf1ea5c052f944a736d67e39ff30}")
	public String SECRET;

	@Value("${wx.imageDir:image/}")
	public String imageDir;

	@Value("${wx.headImageDir}")
	protected String headimagedir;

	@Value("${wx.open.appid}")
	protected String openAppid;

	@Value("${wx.open.secret}")
	protected String openAppSecret;

	protected SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");

	/**
	 * 滑动验证码
	 */
	IAcsClient client = null;
	/**
	 * 实人认证
	 */
	IAcsClient aclient;

	@PostConstruct
	public void initAliyunClient() throws ClientException {
		IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", WeiXinConf.accessKeyId, WeiXinConf.accessKeySecret);
		client = new DefaultAcsClient(profile);

		DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", "afs", "afs.aliyuncs.com");

		DefaultProfile profile1 = DefaultProfile.getProfile("cn-hangzhou", WeiXinConf.accessKeyId, WeiXinConf.accessKeySecret);
		aclient = new DefaultAcsClient(profile1);
	}

	/**
	 * 验证下载文件名不能有特殊字符
	 *
	 * @param fileId 文件id
	 */
	public void validChar(String fileId) {
		char[] chars = fileId.toCharArray();

		for (char c : chars) {
			if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '-' || c == '.') {
				continue;
			} else {
				throw new NoteException("文件名不合法");
			}

		}

	}

	/**
	 * 分页参数验证
	 *
	 * @param start 开始
	 * @param limit 条数
	 */
	public void validPage(Integer start, Integer limit) {
		if (start == null || limit == null) {
			throw new NoteException("分页参数不能为空");
		}

		if (limit > 200)
			limit = 200;
	}

	// 字符串转时间
	@InitBinder
	protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
		// 对于需要转换为Date类型的属性，使用DateEditor进行处理
		binder.registerCustomEditor(Date.class, new DateEditor());
		binder.setValidator(validator);
	}

	public Long getUserId(HttpServletRequest request) {
		if (request.getAttribute("userId") != null && !request.getAttribute("userId").toString().contains("null")) {
			String userId = request.getAttribute("userId").toString();
			return Long.parseLong(userId);
		}

		Cookie[] cookies = request.getCookies();
		if (cookies == null) {
			throw new NoteException("cookie为空,请从公众号重新进入");
		}
		for (Cookie c : cookies) {
			if (c.getName().equalsIgnoreCase("userId")) {
				try {
					return Long.parseLong(c.getValue());
				} catch (NumberFormatException e) {
					logger.error("error cookie userId = " + c.getValue());
					throw new NoteException("获取用户id出错,请从公众号重新进入");
				}
			}
		}

		throw new NoteException("获取用户id出错,请从公众号重新进入");
	}

	/**
	 * 查询cookie中的user
	 *
	 * @param request 请求
	 * @return User
	 */
	public User getUser(HttpServletRequest request) {
		String uuid = "";

		// 先从request中取
		if (request.getAttribute("userId") != null)
			uuid = request.getAttribute("userId").toString();

		if (StringUtils.isEmpty(uuid) || "null".equals(uuid))
			uuid = getUserCookie(request, "userId");

		User user = beanDao.quickQueryOne(User.class, "uuid", uuid);
//		if (user == null)
//			throw new NoteException("请先登录");

		return user;
	}

	/**
	 * 获取管理员用户
	 *
	 * @param request 请求
	 * @return backuser
	 */
	public BackUser getBackUser(HttpServletRequest request) {
		String uuid = getUserCookie(request, "backUserId");

		if (StringUtils.isEmpty(uuid)) {
			throw new NoteException("管理员未登录");
		}

		BackUser user = beanDao.quickQueryOne(BackUser.class, "uuid", uuid);

		if (user == null) {
			throw new NoteException("管理员未登录");
		}

		user.setPassword(null);
		user.setUuid(null);
		return user;
	}

	/**
	 * 千言微信用户加入到cookie
	 *
	 * @param response 返回
	 * @param uuid uuid
	 */
	public void addUserToCookie(HttpServletResponse response, String uuid) {
		Cookie cookie = new Cookie("userId", uuid + "");
		cookie.setPath("/");// 这个要设置
		cookie.setMaxAge(365 * 24 * 60 * 60);
		// logger.info("--------------session cookie: " +
		// JSONObject.toJSONString(cookie));
		response.addCookie(cookie);
	}

	/**
	 * 添加自定义cookie
	 *
	 * @param response 返回
	 * @param name 名称
	 * @param value 值
	 */
	public void addUserCookie(HttpServletResponse response, String name, String value) {
		Cookie cookie = new Cookie(name, value);
		cookie.setPath("/");
		cookie.setMaxAge(2 * 24 * 60 * 60);
		// logger.info("--------------session cookie: " +
		// JSONObject.toJSONString(cookie));
		response.addCookie(cookie);
	}

	/**
	 * 获取自定义cookie
	 *
	 * @param request 请求
	 * @param name 名称
	 * @return String
	 */
	public String getUserCookie(HttpServletRequest request, String name) {
		Cookie[] cookies = request.getCookies();
		// logger.info("--------------session cookie: " +
		// JSONObject.toJSONString(cookies));
		if (cookies == null)
			return null;
		for (Cookie c : cookies) {
			if (c.getName().equalsIgnoreCase(name)) {
				return c.getValue();
			}
		}

		return null;
	}

	/**
	 * 通用的错误处理
	 *
	 * @param e 异常
	 * @param response 返回
	 * @param request 请求
	 * @throws IOException io
	 * @throws EmailException email异常
	 */
	@ExceptionHandler(Exception.class)
	public void handleExceptions(Exception e, HttpServletResponse response, HttpServletRequest request) throws IOException, EmailException {
		// logger.error("", e);
		generateErrMsg(e, request);

		BaseResult result = new BaseResult();
		result.setSuccess(false);
		result.setMessage("出错了 : " + e.getMessage());

		response.getContentType();
		response.setStatus(HttpStatus.SC_OK);
		response.addHeader("content-type", "text/plain");
		response.setContentType("text/plain");
		PrintWriter writer = response.getWriter();
		writer.write(JSON.toJSONString(result));
		writer.flush();

	}

	@ExceptionHandler(NoteException.class)
	@ResponseBody
	public BaseResult handleNoteException(Exception ie, HttpServletResponse response, HttpServletRequest request) throws IOException, EmailException {
		// logger.error("", ie);

		BaseResult result = new BaseResult();
		result.setSuccess(false);
		result.setMessage(ie.getMessage());

		// 生成错误消息
		// generateErrMsg(ie, request);

		return result;
	}

	/**
	 * 生成错误邮件内容,并且保存到数据库
	 *
	 * @param e 异常
	 * @param request request
	 * @return String
	 * @throws IOException io
	 */
	public String generateErrMsg(Exception e, HttpServletRequest request) throws IOException {
		String msg = "";
		String body = "";
		String parameter = request.getParameterMap().toString();
		String agent = request.getHeader("user-agent");
		String requestStr = request.toString();
		msg += "requestStr : " + requestStr + "\n<br>";
		msg += "agent : " + agent + "\n<br>";
		msg += "parameter : " + parameter + "\n<br>";
		String url = request.getRequestURL().toString();
		msg += "url : " + url + "\n<br>";

		try {
			BufferedReader br = request.getReader();
			String inputLine;
			while ((inputLine = br.readLine()) != null) {
				body += inputLine;
			}
			br.close();
			msg += "body : " + body + "\n<br>";
		} catch (Exception e1) {
			// 不包含reader的请求
		}

		// 添加错误堆栈内容
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		e.printStackTrace(pw);

		msg += sw.toString();

		// int i = 0;
		// for (String str : sw.toString().split("\n")) {
		// msg += str + "\n";
		// i++;
		// if (i > 5)
		// break;
		// }

		// 保存到日志表
		// ExceptionMsg em = new ExceptionMsg();
		// em.setAgent(agent);
		// em.setBody(body);
		// em.setParameter(parameter);
		// em.setRequestStr(requestStr);
		// em.setClazz(e.getClass().getName());
		// beanDao.save(em);

		logger.info("exception message = " + msg);
		return msg;
	}

	@ExceptionHandler({ IllegalArgumentException.class, MethodArgumentNotValidException.class })
	@ResponseBody
	public BaseResult handleIllegalArgumentExceptions(Throwable ie) {
		logger.error("", ie);

		BaseResult result = new BaseResult();
		result.setSuccess(false);
		result.setMessage(ie.getMessage());

		return result;
	}

	/**
	 * 获取用户openid
	 *
	 * @param request HttpServletRequest
	 * @return String
	 */
	public String getUserOpenid(HttpServletRequest request) {
		if (request.getAttribute("openid") != null && !request.getAttribute("openid").toString().contains("null")) {
			String openid = request.getAttribute("openid").toString();
			return openid;
		}

		Cookie[] cookies = request.getCookies();
		if (cookies == null) {
			throw new NoteException("cookie为空,请从公众号重新进入");
		}
		for (Cookie c : cookies) {
			if (c.getName().equalsIgnoreCase("openid")) {
				try {
					return c.getValue();
				} catch (NumberFormatException e) {
					logger.error("error cookie openid = " + c.getValue());
					throw new NoteException("获取用户openid出错,请从公众号重新进入");
				}
			}
		}

		// logger.info("--------------session cookie: " +
		// JSONObject.toJSONString(cookies));
		throw new NoteException("获取用户openid出错,请从公众号重新进入");
	}

	/**
	 * 根据name查询系统参数的value
	 *
	 * @param name 名称
	 * @return string
	 */
	public String getSystemParaValue(String name) {
		return beanDao.quickQueryOne(SystemPara.class, "name", name).getValue();
	}

	public double getSystemParaValueDouble(String name) {
		return Double.parseDouble(beanDao.quickQueryOne(SystemPara.class, "name", name).getValue());
	}

	public int getSystemParaValueInt(String name) {
		return Integer.parseInt(beanDao.quickQueryOne(SystemPara.class, "name", name).getValue());
	}

	/**
	 * 请求中读取文件信息
	 *
	 * @param multipartRequest 上传文件请求
	 *
	 * @return 上传文件的信息对象
	 */
	protected MultipartFile getFile(MultipartRequest multipartRequest) {
		// 获得文件单个上传文件：
		MultipartFile file = null;

		// 获取文件名列表
		Iterator<String> it = multipartRequest.getFileNames();

		// 循环遍历列表
		while (it.hasNext()) {
			// 提取文件名
			String fileName = it.next();
			// 获取文件
			file = multipartRequest.getFile(fileName);
		}
		return file;
	}

	protected MultipartFile getFile(HttpServletRequest request) {
		// 转型为MultipartHttpRequest：
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		// 获得文件单个上传文件：
		return getFile((MultipartRequest) multipartRequest);
	}

	public static String getCellValue(Cell cell) {
		String cellValue = "";
		if (cell == null) {
			return cellValue;
		}
		// 把数字当成String来读，避免出现1读成1.0的情况
		if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
			cell.setCellType(Cell.CELL_TYPE_STRING);
		}
		// 判断数据的类型
		switch (cell.getCellType()) {
			case Cell.CELL_TYPE_NUMERIC: // 数字
				cellValue = String.valueOf(cell.getNumericCellValue());
				break;
			case Cell.CELL_TYPE_STRING: // 字符串
				cellValue = String.valueOf(cell.getStringCellValue());
				break;
			case Cell.CELL_TYPE_BOOLEAN: // Boolean
				cellValue = String.valueOf(cell.getBooleanCellValue());
				break;
			case Cell.CELL_TYPE_FORMULA: // 公式
				cellValue = String.valueOf(cell.getCellFormula());
				break;
			case Cell.CELL_TYPE_BLANK: // 空值
				cellValue = "";
				break;
			case Cell.CELL_TYPE_ERROR: // 故障
				cellValue = "非法字符";
				break;
			default:
				cellValue = "未知类型";
				break;
		}
		return cellValue;
	}

	/**
	 * 获取账单号
	 *
	 * @return string
	 */
	public synchronized String getBillNum() {
		SystemPara para = beanDao.quickQueryOne(SystemPara.class, "name", "billNumber");

		Integer billNum = Integer.parseInt(para.getValue());
		// 10位数结果
		DecimalFormat df1 = new DecimalFormat("00000000");

		// 记录自增1
		billNum = billNum + 1;
		if (billNum.intValue() == 10000000)
			billNum = 0;

		para.setValue(billNum.toString());
		// opDao.updateSystemPara("billNumber", billNum.toString());
		beanDao.save(para);

		return df.format(new Date()) + df1.format(billNum);
	}

	/**
	 * 四舍五入
	 *
	 * @param in in
	 * @return double
	 */
	public double halfUp(double in) {
		return halfUp(in, 2);
	}

	/**
	 * 四舍五入保留number位小数
	 *
	 * @param in in
	 * @param number 数字
	 * @return double
	 */
	public double halfUp(double in, int number) {
		try {
			BigDecimal bg = new BigDecimal(in);
			return bg.setScale(number, BigDecimal.ROUND_HALF_UP).doubleValue();
		} catch (Exception e) {
			return 0;
		}
	}

	public GeneralResult permission(){
		return null;
	}
}
